home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/python
- # Class for finding out what partitions are available to us to mount, via /proc/partitions, /etc/mtab and /etc/fstab
- # NOTE: Only works for devices that are 3 char block devices in /dev/ and udev systems.
-
- import gtk
- import gtk.glade
- import os
- import sys
- import popen2
-
- # Line the /proc/partition starts showing drive data
- STARTLINE = 2
- # Length of "/dev/" in chars
- DEVLEN = 5
- # Bytes in a block
- BLOCKSIZE=1024
- AMILLION = 1000000
- # Device prefix
- DEV="/dev/"
- # fstab line 'users', means the device is mountable/unmountable by all users
- USERS_MOUNTABLE="users"
- USER_MOUNTABLE="user"
-
- # Get our effective user ID so we know if we can mount/unmount certain partitions
- UID=os.geteuid()
- ROOT=0
-
- if not os.path.exists("pymou.glade"):
- DATA_DIR="/usr/share/pymou/"
- else:
- print "Using relative directory structure"
- DATA_DIR=""
-
-
- # Partition object, contains information about the partition
- class Partition:
- def __init__(self, procline):
- partdata = procline.split()
- self.major = partdata[0]
- self.minor = partdata[1]
- self.blocks = partdata[2]
- self.name = partdata[3]
- self.disk = partdata[3][:3]
- self.size = int(self.blocks) * BLOCKSIZE / AMILLION
- if not self.name == self.disk:
- self.parent = False
- self.partNum = partdata[3][3:]
- if int(self.partNum) <= 4:
- self.primary = True
- self.logical = False
- else:
- self.primary = False
- self.logical = True
- else:
- self.parent = True
- self.mounted = False
- self.mountpoint = ""
- self.fstabIndex = -1
- self.fs = "unknown"
- self.users = self.user = False # Is the partition mountable by anyone?
-
- def toString(self):
- return "%s %s %s %s %s" % (self.major, self.minor, self.blocks, self.name, self.disk)
-
- # Reads partition information from mtab, fstab and /proc/partitions and generates Partition objects
- class PartInfo:
- def __init__(self):
- self.partitions = {}
- self.partitionTree = {}
- self.fstab = []
-
- def readProcFile(self, procfile):
- partLines = open(procfile).readlines()
- self.buildPartitionDict(partLines)
- self.buildPartitionTree()
-
- def buildPartitionTree(self):
- self.partitionTree = {}
- for partition in self.partitions:
- if not self.partitions[partition].parent:
- disk = self.partitions[partition].disk
- try:
- self.partitionTree[disk].append(partition)
- except KeyError:
- self.partitionTree[disk] = []
- self.partitionTree[disk].append(partition)
- for partition in self.partitionTree:
- self.partitionTree[partition].sort()
-
- def buildPartitionDict(self, partLines):
- for line in partLines[STARTLINE:]:
- #ignore devices that are not sdXY or hdXY.
- split = line.split()
- for x in ["h", "s"]:
- if split[3][0] == x:
- partition = Partition(line)
- if not self.partitions.has_key(partition.name):
- self.partitions[partition.name] = partition
-
- def printPartitionDict(self):
- for partition in self.partitions:
- print self.partitions[partition].toString()
-
- def printPartitionTree(self):
- for partition in self.partitionTree:
- print partition
- outline = "-"
- for part in self.partitionTree[partition]:
- outline += " " + part
- print outline
-
- def resetMounted(self):
- for partition in self.partitions:
- self.partitions[partition].mounted = False
- # self.partitions[partition].mountpoint = ""
-
- def readMtab(self, mtabfile):
- self.resetMounted()
- mountLines = open(mtabfile).readlines()
- for line in mountLines:
- split = line.split()
- if split[0].find(DEV) >= 0:
- device = split[0][DEVLEN:]
- try:
- self.partitions[device].mounted = True
- self.partitions[device].mountpoint = split[1]
- self.partitions[device].fs = split[2]
- except KeyError:
- print "Warning: device %s is mounted, but does not exist" % (device)
-
- def readFstab(self, fstabfile):
- self.fstab = open(fstabfile).readlines()
- for partition in self.partitions:
- self.partitions[partition].fstabIndex = -1
- for x in range(len(self.fstab)):
- line = self.fstab[x] = self.fstab[x].strip()
- if line == "" or line[0] == '#':
- continue
- split = line.split()
- if split[0].find(DEV) >= 0:
- device = split[0][DEVLEN:]
- try:
- self.partitions[device].fstabIndex = x
- if line.find(USERS_MOUNTABLE) >= 0:
- self.partitions[device].users = True
- else:
- self.partitions[device].users = False
- if line.find(USER_MOUNTABLE) >= 0:
- self.partitions[device].user = True
- else:
- self.partitions[device].user = False
- except KeyError:
- print "Warning: device %s is in fstab, but does not exist" % (device)
-
- def printMounted(self):
- for partition in self.partitions:
- if self.partitions[partition].mounted:
- print "%s mounted on %s" % (partition, self.partitions[partition].mountpoint)
-
- # Wrapper for gtk.glade.XML, let's objects be called with xml.widget instead of xml.get_widget(widget)
- class GladeObj(gtk.glade.XML):
- def __getattr__(self, attr):
- try:
- return self.get_widget(attr)
- except KeyError:
- print "No such widget"
-
- # Overrides stdout
- class Output:
- def __init__(self, outfunc):
- self.output = outfunc
-
- def write(self, text):
- self.output(text)
-
-
- # Wrapper class for mount/unmount commands
- class Mounter:
- def __init__(self):
- self.commands = {}
- self.commands['mount'] = "mount"
- self.commands['unmount'] = "umount"
-
- def execCmd(self, cmd):
- pop = popen2.Popen4(cmd)
- ret = pop.wait()
- output = pop.fromchild.read().strip()
- return ret, output
-
- def mount(self, device, location, fs=None):
- device = "%s%s"%(DEV, device)
- args = [device, location]
- command = "%s %s" % (self.commands['mount'], ' '.join(args))
-
- ret, output = self.execCmd(command)
- if not output == "":
- print output
- return ret
- # fd = os.popen3(command, 'r')
- # output = fd[1].read()
- # output += fd[2].read()
- # output.strip()
- # fd = os.popen(command, 'r')
- # output = fd.read()
- # output.strip()
- # print output
- # return
-
- def unmount(self, location):
- args = [location]
- command = "%s %s" % (self.commands['unmount'], ' '.join(args))
-
- ret, output = self.execCmd(command)
- if not output == "":
- print output
- return ret
- # fd = os.popen3(command, 'r')
- # output = fd[1].read()
- # output += fd[2].read()
- # output.strip()
- #
- # print output
- # return
-
- class MountGui:
- def __init__(self):
- self.xml = GladeObj(DATA_DIR+"pymou.glade")
- self.outputBuffer = self.xml.outputView.get_buffer()
- # Overwrite stdout and stderr to our output window
- sys.stdout = Output(self.output)
- sys.stderr = Output(self.output)
-
- self.mounter = Mounter()
- self.partInfo = PartInfo()
- self.partInfo.readProcFile("/proc/partitions")
- self.partInfo.readMtab("/etc/mtab")
- self.partInfo.readFstab("/etc/fstab")
-
- self.buildPartStore()
- self.buildPartSelection()
- self.updatePartStore()
- self.updateFstabView()
- self.connectHandlers()
-
- def buildPartStore(self):
- # (icon name, partition name, mountpoint)
- self.partStore = gtk.TreeStore(str, str, str)
- column = gtk.TreeViewColumn()
- cellPB = gtk.CellRendererPixbuf()
- cellStr = gtk.CellRendererText()
- cellMnt = gtk.CellRendererText()
- column.pack_start(cellPB, False)
- column.add_attribute(cellPB, 'stock-id', 0)
- column.pack_start(cellStr, True)
- column.set_attributes(cellStr, text=1)
- column.pack_start(cellMnt, True)
- column.set_attributes(cellMnt, text=2)
- column.set_widget(None)
- self.xml.partView.append_column(column)
- self.xml.partView.set_headers_visible(False)
- self.xml.partView.set_model(self.partStore)
-
- def buildPartSelection(self):
- self.partSelection = self.xml.partView.get_selection()
- self.partSelection.set_select_function(self.part_selected, None)
-
- def updatePartStore(self):
- self.partStore.clear()
- for part in self.partInfo.partitionTree:
- parentIter = self.partStore.append(None, (gtk.STOCK_HARDDISK, part, ""))
- for subpart in self.partInfo.partitionTree[part]:
- if self.partInfo.partitions[subpart].mounted:
- if not self.partInfo.partitions[subpart].users and not UID == ROOT:
- icon = gtk.STOCK_DIALOG_AUTHENTICATION
- else:
- icon = gtk.STOCK_YES
- else:
- if self.partInfo.partitions[subpart].user or self.partInfo.partitions[subpart].users or UID == ROOT:
- icon = gtk.STOCK_NO
- else:
- icon = gtk.STOCK_DIALOG_AUTHENTICATION
- self.partStore.append(parentIter, (icon , subpart, self.partInfo.partitions[subpart].mountpoint))
- self.xml.partView.expand_all()
-
- def updateFstabView(self):
- fstabBuffer = self.xml.fstabView.get_buffer()
- fstab = ""
- for line in self.partInfo.fstab:
- fstab += line + '\n'
- fstabBuffer.set_text(fstab)
- self.xml.fstablabel.set_label("<b>Fstab</b>")
-
-
- def connectHandlers(self):
- self.xml.mountbtn.connect('clicked', self.mount)
- self.xml.unmountbtn.connect('clicked', self.unmount)
- self.xml.refreshbtn.connect('clicked', self.refresh)
- self.xml.clearbtn.connect('clicked', self.clear)
- self.xml.mntpointbtn.connect('clicked', self.showFolderChooser)
- self.xml.savefstabbtn.connect('clicked', self.saveFstab)
- self.xml.outputView.connect('expose_event', self.outputUnbold)
- self.xml.fstabView.connect('expose_event', self.fstabUnbold)
- self.xml.folderchooser.connect('response', self.choseMountpoint)
- self.xml.pymou.connect('destroy', self.quit)
-
- def part_selected(self, path, args):
- iter = self.partStore.get_iter(path)
- partition = self.partInfo.partitions[self.partStore.get_value(iter, 1)]
-
- self.xml.majorlabel.set_label(partition.major)
- self.xml.minorlabel.set_label(partition.minor)
- self.xml.blocklabel.set_label(partition.blocks)
- self.xml.sizelabel.set_label(str(partition.size))
- try:
- # Set the labels to what we want and change the mount/unmount button active status.
- if partition.mounted:
- mounted = "Yes"
- self.xml.mountbtn.set_property('sensitive', False)
- self.xml.unmountbtn.set_property('sensitive' ,True)
- # self.xml.clearbtn.set_property('sensitive', False)
- else:
- self.xml.mountbtn.set_property('sensitive', True)
- self.xml.unmountbtn.set_property('sensitive' ,False)
- # self.xml.clearbtn.set_property('sensitive', True)
- mounted = "No"
- if partition.logical == True:
- type = "Logical"
- else:
- type = "Primary"
- self.xml.mountedlabel.set_label(mounted)
- self.xml.typelabel.set_label(type)
- self.xml.fslabel.set_label(partition.fs)
- self.xml.mountpointlabel.set_label(partition.mountpoint)
- if partition.fstabIndex >= 0:
- self.xml.fstabentrylabel.set_label(self.partInfo.fstab[partition.fstabIndex])
- else:
- self.xml.fstabentrylabel.set_label("")
- self.xml.mntpointbtn.set_property('sensitive', True)
- self.xml.clearbtn.set_property('sensitive', True)
-
- except AttributeError:
- self.xml.mountedlabel.set_label("")
- self.xml.mountpointlabel.set_label("")
- self.xml.fstabentrylabel.set_label("")
- self.xml.typelabel.set_label("")
- self.xml.fslabel.set_label("none")
- self.xml.mntpointbtn.set_property('sensitive', False)
- self.xml.mountbtn.set_property('sensitive', False)
- self.xml.unmountbtn.set_property('sensitive' ,False)
- self.xml.clearbtn.set_property('sensitive', False)
-
- return True
-
- def refresh(self, obj=None):
- print "Rereading Partition Information"
-
- self.partInfo.readProcFile("/proc/partitions")
- self.partInfo.readMtab("/etc/mtab")
- self.partInfo.readFstab("/etc/fstab")
-
- self.updatePartStore()
- self.updateFstabView()
-
- def clear(self, obj):
- model, iter = self.partSelection.get_selected()
- device = model.get_value(iter, 1)
- mountpoint = ""
- print "Clearing mount point for %s" % (device)
- self.partInfo.partitions[device].mountpoint = mountpoint
- model.set_value(iter, 2, mountpoint)
-
-
- def mount(self, obj):
- model, iter = self.partSelection.get_selected()
- device = model.get_value(iter, 1)
- mountpoint = self.partInfo.partitions[device].mountpoint
- fstabIndex = self.partInfo.partitions[device].fstabIndex
- if mountpoint == "" and fstabIndex < 0:
- print "Warning: Mountpoint undefined and no entry in fstab for device %s" % device
- return
- if not mountpoint == "":
- print "mounting %s at %s" % (device, mountpoint)
- else:
- print "mounting %s" % (device)
- if not self.mounter.mount(device, mountpoint) == 0:
- if self.partInfo.partitions[device].fstabIndex >= 0:
- print "mounting %s at %s failed, trying to mount according to fstab" % (device, mountpoint)
- if self.mounter.mount(device, "") == 0:
- print "Successfully mounted %s" % (device)
- else:
- print "Successfully mounted %s" % (device)
-
- self.refresh()
-
- def unmount(self, obj):
- model, iter = self.partSelection.get_selected()
- device = model.get_value(iter, 1)
- if self.partInfo.partitions[device].mounted:
- mountpoint = self.partInfo.partitions[device].mountpoint
- print "unmounting %s from %s" % (device, mountpoint)
- ret = self.mounter.unmount(mountpoint)
- self.refresh()
- else:
- print "Warning: %s is not mounted" % device
- return
-
-
- def output(self, text):
- end_iter = self.outputBuffer.get_end_iter()
- self.outputBuffer.insert(end_iter, text)
- end_mark = self.outputBuffer.create_mark(None, self.outputBuffer.get_end_iter(), True)
- self.xml.outputView.scroll_to_mark(end_mark, 0)
- self.xml.outputlabel.set_label("<b>Output</b>")
-
- def outputUnbold(self, obj, data):
- self.xml.outputlabel.set_label("Output")
-
- def fstabUnbold(self, obj, data):
- self.xml.fstablabel.set_label("Fstab")
-
- def showFolderChooser(self, obj):
- self.xml.folderchooser.present()
-
- def choseMountpoint(self, obj, response):
- if response == gtk.RESPONSE_OK:
- model, iter = self.partSelection.get_selected()
- device = model.get_value(iter, 1)
- mountpoint = self.xml.folderchooser.get_filename()
- self.partInfo.partitions[device].mountpoint = mountpoint
- model.set_value(iter, 2, mountpoint)
- print "Setting %s to mount at %s" % (device, mountpoint)
- else:
- pass
- self.xml.folderchooser.hide()
-
- def saveFstab(self, obj):
- for partition in self.partInfo.partitions:
- device = self.partInfo.partitions[partition]
- if device.mountpoint == "":
- continue
- if device.fs == "unknown":
- fs = "auto"
- else:
- fs = device.fs
- fstabentry = "%s%s\t %s\t %s\t defaults 0 0" % (DEV, device.name, device.mountpoint, fs)
-
- if device.fstabIndex >= 0:
- self.partInfo.fstab[device.fstabIndex] = fstabentry
- else:
- self.partInfo.fstab.append(fstabentry)
- # The fstabIndex will now be the last line in the fstab, where we just appended the line
- device.fstabIndex = len(self.partInfo.fstab) - 1
- self.updateFstabView()
- return
-
- def quit(self, obj):
- gtk.main_quit()
-
-
- driver = MountGui()
- gtk.main()
-